// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022.
 * Description: jitter_entropy support.
 * Create: 2023-10-30
*/

#include <crypto/rng.h>
#include <linux/err.h>
#include <linux/vmalloc.h>
#include <linux/uaccess.h>
#include <linux/jitter_entropy.h>

static struct crypto_rng *jitter_entropy;
static DEFINE_SPINLOCK(jitter_spinlock);

int euler_jitter_entropy(char __user *ubuf, size_t len)
{
	uint8_t *entropy_bits;
	int err;

	if (unlikely(jitter_entropy == NULL)) {
		spin_lock(&jitter_spinlock);
		if (jitter_entropy == NULL) {
			jitter_entropy = crypto_alloc_rng("jitterentropy_rng", 0, 0);
			if (IS_ERR(jitter_entropy)) {
				spin_unlock(&jitter_spinlock);
				return PTR_ERR(jitter_entropy);
			}
		}
		spin_unlock(&jitter_spinlock);
	}
	entropy_bits = kmalloc(len, GFP_KERNEL);
	if (!entropy_bits)
		return -ENOMEM;
	err = crypto_rng_get_bytes(jitter_entropy, entropy_bits, len);
	if (err == 0 && copy_to_user(ubuf, entropy_bits, len) != 0)
		err = -EFAULT;
	memzero_explicit(entropy_bits, len);
	kfree(entropy_bits);
	return err < 0 ? err : len;
}

